<!doctype html>
<!--
Copyright 2018 Google, Inc. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<link rel="stylesheet" href="style.css">

<div class="bar">
</div>
<header class="profile">
  <img src="avatar.jpg" class="avatar">
  <h1 class="name">Surma</h1>
  <h2 class="handle">@DasSurma</h2>
  <section class="description">
    Web Advocate. Internetrovert. Craving simplicity, finding it nowhere. Engineer <a href="#">@Google</a>
    <br/>
    <br/>
    <a href="#">keybase.io/surma</a>
  </section>
  <section class="meta">
    <span class="location">London, UK</span>
    <a class="homepage" href="https://dassur.ma">dassur.ma</a>
  </section>
  <section class="stats">
    <span class="following">1,337</span> Following
    <span class="followers">9,659</span> Followers
  </section>
  <button class="follow">Follow</button>
</header>
<section class="tweets">
  <section class="tweet">
    <img src="avatar.jpg" class="avatar">
    <section class="meta"> <span class="name">Surma</span>
      <span class="handle">@DasSurma</span>
      <span class="date">Dec 27</span>
    </section>
    📝 New post-🎄 blog post about architecture and web apps: The Actor Model and why I think it implies that DOM-in-workers is undesirable.
    <section class="media">
      <img src="media.jpg">
      <p class="title">“An Actor, a model and an architect walk onto the web...” – DasSur.ma</p>
      <p class="domain">dassur.ma</p>
    </section>
  </section>
  <section class="tweet">
    <img src="avatar.jpg" class="avatar">
    <section class="meta">
      <span class="name">Surma</span>
      <span class="handle">@DasSurma</span>
      <span class="date">Dec 27</span>
    </section>
    📝 New post-🎄 blog post about architecture and web apps: The Actor Model and why I think it implies that DOM-in-workers is undesirable.
    <section class="media">
      <img src="media.jpg">
      <p class="title">“An Actor, a model and an architect walk onto the web...” – DasSur.ma</p>
      <p class="domain">dassur.ma</p>
    </section>
  </section>
</section>
<script>
  if (location.protocol === 'http:' && location.hostname !== 'localhost') {
    location.protocol = 'https:';
  }
  var animationWorklet = window.animationWorklet;
  if (CSS)
    animationWorklet = CSS.animationWorklet;

  if (!animationWorklet) {
    document.body.innerHTML = 'You need support for <a href="https://wicg.github.io/animation-worklet/">Animation Worklet</a> to view this demo :(';
  }

  [
    '--avatar-size',
    '--avatar-border',
    '--header-height',
    '--font-base',
    '--bar-height',
    '--spacer',
  ].forEach(name => {
    CSS.registerProperty({
      name,
      syntax: '<length>',
      initialValue: '0px',
      inherits: true
    });
  });

  async function init() {
    await animationWorklet.addModule('twitter-header-animator.js');
    const scrollSource = document.body;
    const bar = document.querySelector('.bar');
    const avatar = document.querySelector('.profile .avatar');
    const follow = document.querySelector('.profile .follow');
    const name = document.querySelector('.profile .name');
    const timeRange = 1000;
    const scrollTimeline = new ScrollTimeline({scrollSource, timeRange});

    const barEffect = new KeyframeEffect(
      bar,
      [
        {opacity: 0},
        {opacity: 1},
      ],
      {
        duration: /*timeWhenAvatarTouchesTop*/ 0,
        fill: 'both',
      }
    );
    new WorkletAnimation(
      'twitter-header',
      barEffect,
      scrollTimeline,
      []
    ).play();
    const avatarEffect = new KeyframeEffect(
      avatar,
      [
        {transform: `translateY(0) scale(1)`},
        {transform: `translateY(0px) scale(${0/*targetAvatarScale*/})`, offset: 0/*timeWhenAvatarTouchesTop/timeRange*/},
        {transform: `translateY(${0/*maxAvatarOffset*/}px) scale(${0/*targetAvatarScale*/})`},
      ],
      {
        duration: timeRange,
        fill: 'both',
      }
    );
    new WorkletAnimation(
      'twitter-header',
      avatarEffect,
      scrollTimeline,
      []
    ).play();

    const followEffect = new KeyframeEffect(
      follow,
      [
        {transform: `translateY(0)`},
        {transform: `translateY(0)`, offset: 0/*timeWhenFollowTouchesTop/range*/},
        {transform: `translateY(${0/*maxAvatarOffset*/}px)`},
      ],
      {
        duration: timeRange,
        fill: 'both',
      }
    );
    new WorkletAnimation(
      'twitter-header',
      followEffect,
      scrollTimeline,
      []
    ).play();

    const nameEffect = new KeyframeEffect(
      name,
      [
        {transform: `translateY(0)`},
        {transform: `translateY(0)`, offset: 0/*timeWhenFollowTouchesTop/timeRange*/},
        {transform: `translateY(0) translateX(${0/*scrollSourceStyles.get('--bar-height').value*/}px)`, offset: 0/*timeWhenNameTouchesTop/timeRange*/},
        {transform: `translateY(${0/*maxNameOffset*/}px) translateX(${0/*scrollSourceStyles.get('--bar-height').value*/}px)`},
      ],
      {
        duration: timeRange,
        fill: 'both',
      }
    );
    new WorkletAnimation(
      'twitter-header',
      nameEffect,
      scrollTimeline,
      []
    ).play();

    function updateTimings() {
      const scrollSourceStyles = document.body.computedStyleMap();
      const viewportHeight = scrollSource.clientHeight;
      const maxScroll = scrollSource.scrollHeight - viewportHeight;

      const avatarDistanceFromTop = scrollSourceStyles.get('--header-height').value / 2 - scrollSourceStyles.get('--avatar-size').value / 2 - scrollSourceStyles.get('--avatar-border').value;
      const timeWhenAvatarTouchesTop = avatarDistanceFromTop / maxScroll * timeRange;
      const maxAvatarOffset = maxScroll - avatarDistanceFromTop;
      const targetAvatarScale = scrollSourceStyles.get('--bar-height').value / (scrollSourceStyles.get('--avatar-size').value + scrollSourceStyles.get('--avatar-border').value * 2);

      const avatarEffectKeyFrames = avatarEffect.getKeyframes();
      avatarEffectKeyFrames[1].transform = `translateY(0px) scale(${targetAvatarScale})`;
      avatarEffectKeyFrames[1].offset = timeWhenAvatarTouchesTop/timeRange;
      avatarEffectKeyFrames[2].transform = `translateY(${maxAvatarOffset}px) scale(${targetAvatarScale})`;
      avatarEffect.setKeyframes(avatarEffectKeyFrames);

      barEffect.duration = timeWhenAvatarTouchesTop;

      const followDistanceFromTop = scrollSourceStyles.get('--header-height').value / 2 + scrollSourceStyles.get('--spacer').value/2;
      const timeWhenFollowTouchesTop = followDistanceFromTop / maxScroll * timeRange;
      const maxFollowOffset = maxScroll - followDistanceFromTop;
      const followEffectKeyFrames = followEffect.getKeyframes();
      followEffectKeyFrames[1].offset = timeWhenFollowTouchesTop/timeRange;
      followEffectKeyFrames[2].transform = `translateY(${maxFollowOffset}px)`;
      followEffect.setKeyframes(followEffectKeyFrames);

      const nameDistanceFromTop = name.offsetTop - scrollSourceStyles.get('--spacer').value;
      const timeWhenNameTouchesTop = nameDistanceFromTop / maxScroll * timeRange;
      const maxNameOffset = maxScroll - nameDistanceFromTop;
      const nameEffectKeyFrames = nameEffect.getKeyframes();
      const nameLeftOffset = scrollSourceStyles.get('--bar-height').value + scrollSourceStyles.get('--spacer').value/2;
      nameEffectKeyFrames[1].offset = timeWhenAvatarTouchesTop/timeRange;
      nameEffectKeyFrames[2].transform = `translateY(0) translateX(${nameLeftOffset}px)`;
      nameEffectKeyFrames[2].offset = timeWhenNameTouchesTop/timeRange;
      nameEffectKeyFrames[3].transform = `translateY(${maxNameOffset}px) translateX(${nameLeftOffset}px)`;
      nameEffect.setKeyframes(nameEffectKeyFrames);
    }
    updateTimings();
    window.addEventListener('resize', _ => updateTimings());

  }
  init();
</script>
